# -*- coding: utf-8 -*-
"""
QAD API RESTful Controller
提供 RESTful API 接口用于访问 QAD 系统数据
"""

import json
import logging
import time
import os
import glob
from datetime import datetime, timedelta

from odoo import http
from odoo.http import request, Response
from odoo.exceptions import ValidationError, AccessError

_logger = logging.getLogger(__name__)


class QADAPIController(http.Controller):
    """QAD API 控制器"""

    def _authenticate_api_key(self, api_key):
        """
        验证 API Key
        返回用户对象，如果验证失败返回 None
        """
        if not api_key:
            _logger.warning("API Key 为空")
            return None
        
        _logger.info(f"开始验证 API Key: {api_key[:8]}...")
        
        try:
            # 使用 Odoo 标准的 API Key 验证方法
            apikey_model = request.env['res.users.apikeys'].sudo()
            
            # 先查看所有 API Key（用于调试）
            all_keys = apikey_model.search([])
            _logger.info(f"系统中总共有 {len(all_keys)} 个 API Key")
            for key in all_keys:
                name = getattr(key, 'name', 'Unknown')
                user_login = key.user_id.login if key.user_id else 'None'
                _logger.info(f"  - Name: {name}, User: {user_login}")
            
            # 使用 Odoo JSON-RPC 相同的验证方法
            # 这是从 ir_http.py 中找到的标准验证方法
            try:
                uid = apikey_model._check_credentials(scope='rpc', key=api_key)
                if uid:
                    user = request.env['res.users'].sudo().browse(uid)
                    if user and user.active:
                        _logger.info(f"API Key 认证成功：用户 {user.login}")
                        return user
                    else:
                        _logger.warning(f"API Key 对应的用户不存在或未激活")
                else:
                    _logger.warning(f"API Key 验证失败：无效的 Key")
                    
            except Exception as auth_error:
                _logger.warning(f"API Key 认证失败：{str(auth_error)}")
            
            return None
            
        except Exception as e:
            _logger.error(f"API Key 认证异常：{str(e)}")
            return None

    def _check_rate_limit(self, endpoint, user):
        """
        检查请求频率限制
        简化实现，实际应该使用缓存或数据库记录
        """
        if not endpoint.rate_limit_per_minute or endpoint.rate_limit_per_minute == 0:
            return True
        
        # TODO: 实现请求频率限制逻辑
        # 可以使用 Redis 或数据库来记录请求时间
        return True

    def _execute_local_script(self, server_config, endpoint):
        """
        执行本地脚本并获取 JSON 文件
        """
        try:
            import subprocess
            
            # 构建命令
            work_path = server_config.work_path
            output_path = server_config.output_path
            app_name = endpoint.application_name
            
            # 切换到工作目录并执行脚本
            cmd = f"cd {work_path} && {app_name}"
            if endpoint.script_parameters:
                cmd += f" {endpoint.script_parameters}"
            
            _logger.info(f"执行本地脚本：{cmd}")
            
            # 执行脚本
            result = subprocess.run(
                cmd,
                shell=True,
                capture_output=True,
                text=True,
                timeout=server_config.execution_timeout
            )
            
            if result.returncode != 0:
                raise Exception(f"脚本执行失败：{result.stderr}")
            
            # 读取输出文件
            return self._read_json_files(output_path, endpoint)
            
        except subprocess.TimeoutExpired:
            raise Exception(f"脚本执行超时（>{server_config.execution_timeout}秒）")
        except Exception as e:
            raise Exception(f"本地脚本执行失败：{str(e)}")

    def _execute_ssh_script(self, server_config, endpoint):
        """
        通过 SSH 执行远程脚本并获取 JSON 文件
        """
        try:
            import paramiko
            from io import StringIO
            
            # 创建 SSH 客户端
            ssh = paramiko.SSHClient()
            ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            
            # 连接参数
            connect_params = {
                'hostname': server_config.host,
                'port': server_config.port,
                'username': server_config.ssh_username,
                'timeout': server_config.connection_timeout,
            }
            
            # 根据认证方式设置参数
            if server_config.auth_type == 'password':
                connect_params['password'] = server_config.ssh_password
            elif server_config.auth_type == 'key':
                # 使用私钥
                if server_config.ssh_private_key:
                    key_file = StringIO(server_config.ssh_private_key)
                    pkey = paramiko.RSAKey.from_private_key(
                        key_file,
                        password=server_config.ssh_key_passphrase
                    )
                    connect_params['pkey'] = pkey
            
            _logger.info(f"连接 SSH：{server_config.host}:{server_config.port}")
            ssh.connect(**connect_params)
            
            # 构建命令
            work_path = server_config.work_path
            output_path = server_config.output_path
            app_name = endpoint.application_name
            
            cmd = f"cd {work_path} && {app_name}"
            if endpoint.script_parameters:
                cmd += f" {endpoint.script_parameters}"
            
            _logger.info(f"执行远程脚本：{cmd}")
            
            # 执行命令
            stdin, stdout, stderr = ssh.exec_command(
                cmd,
                timeout=server_config.execution_timeout
            )
            
            # 获取执行结果
            exit_status = stdout.channel.recv_exit_status()
            if exit_status != 0:
                error_msg = stderr.read().decode()
                raise Exception(f"脚本执行失败：{error_msg}")
            
            # 读取输出文件
            json_data = self._read_remote_json_files(ssh, output_path, endpoint)
            
            ssh.close()
            return json_data
            
        except Exception as e:
            raise Exception(f"SSH 脚本执行失败：{str(e)}")

    def _read_json_files(self, output_path, endpoint):
        """
        读取本地 JSON 文件
        """
        try:
            # 获取文件模式
            pattern = endpoint.json_filename_pattern or '*.json'
            file_pattern = os.path.join(output_path, pattern)
            
            # 查找匹配的文件
            files = glob.glob(file_pattern)
            
            if not files:
                raise Exception(f"未找到匹配的文件：{file_pattern}")
            
            # 过滤时效内的文件
            max_age = timedelta(hours=endpoint.max_file_age_hours)
            current_time = datetime.now()
            
            valid_files = []
            for file_path in files:
                file_time = datetime.fromtimestamp(os.path.getmtime(file_path))
                if current_time - file_time <= max_age:
                    valid_files.append(file_path)
            
            if not valid_files:
                raise Exception(f"未找到时效内的文件（{endpoint.max_file_age_hours}小时）")
            
            # 读取最新的文件
            latest_file = max(valid_files, key=os.path.getmtime)
            _logger.info(f"读取文件：{latest_file}")
            
            with open(latest_file, 'r', encoding='utf-8') as f:
                return json.load(f)
                
        except Exception as e:
            raise Exception(f"读取 JSON 文件失败：{str(e)}")

    def _read_remote_json_files(self, ssh, output_path, endpoint):
        """
        读取远程 JSON 文件
        """
        try:
            # 使用 SFTP 读取文件
            sftp = ssh.open_sftp()
            
            # 获取文件列表
            pattern = endpoint.json_filename_pattern or '*.json'
            
            # 简化处理：列出目录中的所有文件，然后匹配模式
            files = sftp.listdir(output_path)
            
            # 过滤匹配的文件
            import fnmatch
            matched_files = [f for f in files if fnmatch.fnmatch(f, pattern)]
            
            if not matched_files:
                raise Exception(f"未找到匹配的文件：{pattern}")
            
            # 过滤时效内的文件
            max_age = timedelta(hours=endpoint.max_file_age_hours)
            current_time = datetime.now()
            
            valid_files = []
            for filename in matched_files:
                file_path = os.path.join(output_path, filename)
                file_stat = sftp.stat(file_path)
                file_time = datetime.fromtimestamp(file_stat.st_mtime)
                if current_time - file_time <= max_age:
                    valid_files.append((filename, file_stat.st_mtime))
            
            if not valid_files:
                raise Exception(f"未找到时效内的文件（{endpoint.max_file_age_hours}小时）")
            
            # 选择最新的文件
            latest_file = max(valid_files, key=lambda x: x[1])[0]
            latest_file_path = os.path.join(output_path, latest_file)
            
            _logger.info(f"读取远程文件：{latest_file_path}")
            
            # 读取文件内容
            with sftp.open(latest_file_path, 'r') as f:
                content = f.read().decode('utf-8')
                return json.loads(content)
            
        except Exception as e:
            raise Exception(f"读取远程 JSON 文件失败：{str(e)}")
        finally:
            if 'sftp' in locals():
                sftp.close()

    def _process_json_data(self, json_data, server_config, endpoint):
        """
        处理 JSON 数据并生成所需的文件
        
        参数：
        - json_data: 接收到的 JSON 数据
        - server_config: 服务器配置
        - endpoint: 接口配置
        
        返回：
        - 生成的文件路径列表
        """
        ssh_connection = None
        try:
            # 1. 解析 JSON 获取 traceid
            traceid = None
            
            # 检查 JSON 结构并提取 traceid
            if isinstance(json_data, dict):
                # 尝试从 dsBackflushMaster 中获取
                if 'dsBackflushMaster' in json_data:
                    traceid = json_data['dsBackflushMaster'].get('traceid')
                # 或者直接从根级获取
                if not traceid:
                    traceid = json_data.get('traceid')
            
            if not traceid:
                raise Exception('无法从 JSON 数据中提取 traceid')
            
            _logger.info(f"提取到 traceid: {traceid}")
            
            # 2. 构建目录路径
            work_path = server_config.work_path
            output_path = server_config.output_path
            additional_path = endpoint.additional_path or ''
            
            # 清理路径（移除开头和结尾的斜杠）
            additional_path = additional_path.strip('/')
            
            # 构建完整路径
            if additional_path:
                work_dir = os.path.join(work_path, additional_path)
                output_dir = os.path.join(output_path, additional_path)
            else:
                work_dir = work_path
                output_dir = output_path
            
            _logger.info(f"工作目录: {work_dir}")
            _logger.info(f"输出目录: {output_dir}")
            
            # 3. 根据连接类型创建文件
            if server_config.connection_type == 'local':
                file_info = self._create_files_local(
                    json_data, traceid, work_dir, output_dir,
                    server_config, endpoint
                )
            elif server_config.connection_type == 'ssh':
                # SSH模式：创建连接并保持
                ssh_connection = self._create_ssh_connection(server_config)
                file_info = self._create_files_ssh_with_connection(
                    ssh_connection, json_data, traceid, work_dir, output_dir,
                    server_config, endpoint
                )
            else:
                raise Exception('不支持的连接类型')
            
            # 4. 执行脚本处理文件（复用SSH连接）
            _logger.info(f"开始执行脚本处理...")
            if server_config.connection_type == 'ssh' and ssh_connection:
                script_result = self._execute_script_ssh_with_connection(
                    ssh_connection, traceid, work_dir, output_dir, server_config, endpoint
                )
            else:
                script_result = self._execute_processing_script(
                    traceid, work_dir, output_dir, server_config, endpoint
                )
            
            # 5. 处理执行结果
            if script_result.get('success'):
                # SSH 模式下，script_result 已经包含了解析和移动的结果
                if server_config.connection_type == 'ssh':
                    file_info.update({
                        'processing_result': script_result,
                        'script_executed': True
                    })
                else:
                    # 本地模式需要单独解析和移动
                    result_data = self._parse_result_file(
                        traceid, output_dir, server_config, endpoint
                    )
                    
                    # 根据处理结果移动文件
                    self._move_result_files(
                        traceid, output_dir, server_config, endpoint, result_data
                    )
                    
                    file_info.update({
                        'processing_result': result_data,
                        'script_executed': True
                    })
            else:
                file_info.update({
                    'processing_result': script_result,
                    'script_executed': False
                })
            
            return file_info
                
        except Exception as e:
            _logger.error(f"处理 JSON 数据失败: {str(e)}")
            raise
        finally:
            # 确保关闭SSH连接
            if ssh_connection:
                try:
                    ssh_connection.close()
                    _logger.info(f"SSH连接已关闭")
                except:
                    pass

    def _clean_json_for_storage(self, json_data):
        """
        清理JSON数据，移除dataid和traceid根节点键值
        
        参数：
        - json_data: 原始JSON数据
        
        返回：
        - 清理后的JSON数据
        """
        try:
            if isinstance(json_data, dict):
                cleaned_data = json_data.copy()
                
                # 移除根级别的 dataid 和 traceid
                cleaned_data.pop('dataid', None)
                cleaned_data.pop('traceid', None)
                
                # 如果存在 dsBackflushMaster 节点，也移除其中的 dataid 和 traceid
                if 'dsBackflushMaster' in cleaned_data and isinstance(cleaned_data['dsBackflushMaster'], dict):
                    ds_data = cleaned_data['dsBackflushMaster'].copy()
                    ds_data.pop('dataid', None)
                    ds_data.pop('traceid', None)
                    cleaned_data['dsBackflushMaster'] = ds_data
                
                return cleaned_data
            else:
                return json_data
                
        except Exception as e:
            _logger.error(f"清理JSON数据失败: {str(e)}")
            return json_data  # 如果清理失败，返回原始数据
    
    def _create_files_local(self, json_data, traceid, work_dir, output_dir, server_config, endpoint):
        """在本地系统创建所需文件"""
        import subprocess
        
        try:
            # 确保目录存在
            os.makedirs(work_dir, exist_ok=True)
            os.makedirs(output_dir, exist_ok=True)
            
            # 1. 创建 JSON 文件（清理dataid和traceid）
            cleaned_json_data = self._clean_json_for_storage(json_data)
            json_file = os.path.join(work_dir, f"{traceid}.json")
            with open(json_file, 'w', encoding='utf-8') as f:
                json.dump(cleaned_json_data, f, ensure_ascii=False, indent=2)
            _logger.info(f"创建 JSON 文件: {json_file}")
            
            # 2. 创建 .p 文件
            p_file = os.path.join(work_dir, f"{traceid}.p")
            p_content = self._generate_p_file_content(
                traceid, work_dir, output_dir, server_config, endpoint
            )
            with open(p_file, 'w', encoding='utf-8') as f:
                f.write(p_content)
            _logger.info(f"创建 .p 文件: {p_file}")
            
            # 3. 创建 .dat 文件
            dat_file = os.path.join(work_dir, f"{traceid}.dat")
            dat_content = self._generate_dat_file_content(
                traceid, json_file, work_dir, output_dir, server_config, endpoint
            )
            with open(dat_file, 'w', encoding='utf-8') as f:
                f.write(dat_content)
            _logger.info(f"创建 .dat 文件: {dat_file}")
            
            return {
                'json_file': json_file,
                'p_file': p_file,
                'dat_file': dat_file,
                'traceid': traceid
            }
            
        except Exception as e:
            _logger.error(f"本地创建文件失败: {str(e)}")
            raise
    
    def _create_ssh_connection(self, server_config):
        """
        创建并返回SSH连接
        
        参数：
        - server_config: 服务器配置
        
        返回：
        - ssh: SSH客户端连接对象
        """
        import paramiko
        from io import StringIO
        
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        
        # 连接参数
        connect_params = {
            'hostname': server_config.host,
            'port': server_config.port,
            'username': server_config.ssh_username,
            'timeout': server_config.connection_timeout,
        }
        
        # 根据认证方式设置参数
        if server_config.auth_type == 'password':
            connect_params['password'] = server_config.ssh_password
        elif server_config.auth_type == 'key':
            if server_config.ssh_private_key:
                key_file = StringIO(server_config.ssh_private_key)
                pkey = paramiko.RSAKey.from_private_key(
                    key_file,
                    password=server_config.ssh_key_passphrase
                )
                connect_params['pkey'] = pkey
        
        _logger.info(f"连接 SSH：{server_config.host}:{server_config.port}")
        ssh.connect(**connect_params)
        
        return ssh
    
    def _create_files_ssh_with_connection(self, ssh, json_data, traceid, work_dir, output_dir, server_config, endpoint):
        """通过已有SSH连接在远程系统创建所需文件（压缩传输优化）"""
        try:
            from io import BytesIO
            import tarfile
            
            # 确保目录存在
            sftp = ssh.open_sftp()
            self._ensure_remote_dir(sftp, work_dir)
            self._ensure_remote_dir(sftp, output_dir)
            sftp.close()
            
            # 生成文件内容
            json_file = os.path.join(work_dir, f"{traceid}.json")
            p_file = os.path.join(work_dir, f"{traceid}.p")
            dat_file = os.path.join(work_dir, f"{traceid}.dat")
            
            # 清理JSON数据（移除dataid和traceid）
            cleaned_json_data = self._clean_json_for_storage(json_data)
            json_content = json.dumps(cleaned_json_data, ensure_ascii=False, indent=2)
            p_content = self._generate_p_file_content(
                traceid, work_dir, output_dir, server_config, endpoint
            )
            dat_content = self._generate_dat_file_content(
                traceid, json_file, work_dir, output_dir, server_config, endpoint
            )
            
            # 创建内存中的 tar.gz 压缩包
            _logger.info(f"创建压缩包...")
            tar_buffer = BytesIO()
            current_time = time.time()  # 当前时间戳
            
            with tarfile.open(fileobj=tar_buffer, mode='w:gz') as tar:
                # 添加 JSON 文件
                json_info = tarfile.TarInfo(name=f"{traceid}.json")
                json_bytes = json_content.encode('utf-8')
                json_info.size = len(json_bytes)
                json_info.mtime = current_time
                json_info.mode = 0o644
                tar.addfile(json_info, BytesIO(json_bytes))
                
                # 添加 .p 文件
                p_info = tarfile.TarInfo(name=f"{traceid}.p")
                p_bytes = p_content.encode('utf-8')
                p_info.size = len(p_bytes)
                p_info.mtime = current_time
                p_info.mode = 0o644
                tar.addfile(p_info, BytesIO(p_bytes))
                
                # 添加 .dat 文件
                dat_info = tarfile.TarInfo(name=f"{traceid}.dat")
                dat_bytes = dat_content.encode('utf-8')
                dat_info.size = len(dat_bytes)
                dat_info.mtime = current_time
                dat_info.mode = 0o644
                tar.addfile(dat_info, BytesIO(dat_bytes))
            
            tar_buffer.seek(0)
            
            # 上传压缩包
            remote_tar = os.path.join(work_dir, f"{traceid}.tar.gz")
            _logger.info(f"上传压缩包: {remote_tar}")
            
            sftp = ssh.open_sftp()
            with sftp.open(remote_tar, 'wb') as f:
                f.write(tar_buffer.read())
            sftp.close()
            
            # 解压缩
            _logger.info(f"远程解压缩...")
            untar_cmd = f"cd {work_dir} && tar -xzf {traceid}.tar.gz --touch && rm {traceid}.tar.gz"
            stdin, stdout, stderr = ssh.exec_command(untar_cmd)
            exit_status = stdout.channel.recv_exit_status()
            
            if exit_status != 0:
                error_msg = stderr.read().decode()
                raise Exception(f"解压缩失败: {error_msg}")
            
            # 设置文件时间戳
            _logger.info(f"设置文件时间戳...")
            touch_cmd = f"touch {json_file} {p_file} {dat_file}"
            stdin, stdout, stderr = ssh.exec_command(touch_cmd)
            stdout.channel.recv_exit_status()
            
            _logger.info(f"✅ 文件创建完成（压缩传输）")
            
            return {
                'json_file': json_file,
                'p_file': p_file,
                'dat_file': dat_file,
                'traceid': traceid,
                'transfer_method': 'compressed'
            }
            
        except Exception as e:
            _logger.error(f"SSH 创建文件失败: {str(e)}")
            raise
    
    def _create_files_ssh(self, json_data, traceid, work_dir, output_dir, server_config, endpoint):
        """通过 SSH 在远程系统创建所需文件（压缩传输优化）"""
        try:
            import paramiko
            from io import StringIO, BytesIO
            import tarfile
            
            # 创建 SSH 客户端
            ssh = paramiko.SSHClient()
            ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            
            # 连接参数
            connect_params = {
                'hostname': server_config.host,
                'port': server_config.port,
                'username': server_config.ssh_username,
                'timeout': server_config.connection_timeout,
            }
            
            # 根据认证方式设置参数
            if server_config.auth_type == 'password':
                connect_params['password'] = server_config.ssh_password
            elif server_config.auth_type == 'key':
                if server_config.ssh_private_key:
                    key_file = StringIO(server_config.ssh_private_key)
                    pkey = paramiko.RSAKey.from_private_key(
                        key_file,
                        password=server_config.ssh_key_passphrase
                    )
                    connect_params['pkey'] = pkey
            
            _logger.info(f"连接 SSH：{server_config.host}:{server_config.port}")
            ssh.connect(**connect_params)
            
            # 确保目录存在
            sftp = ssh.open_sftp()
            self._ensure_remote_dir(sftp, work_dir)
            self._ensure_remote_dir(sftp, output_dir)
            sftp.close()
            
            # 生成文件内容
            json_file = os.path.join(work_dir, f"{traceid}.json")
            p_file = os.path.join(work_dir, f"{traceid}.p")
            dat_file = os.path.join(work_dir, f"{traceid}.dat")
            
            # 清理JSON数据（移除dataid和traceid）
            cleaned_json_data = self._clean_json_for_storage(json_data)
            json_content = json.dumps(cleaned_json_data, ensure_ascii=False, indent=2)
            p_content = self._generate_p_file_content(
                traceid, work_dir, output_dir, server_config, endpoint
            )
            dat_content = self._generate_dat_file_content(
                traceid, json_file, work_dir, output_dir, server_config, endpoint
            )
            
            # 创建内存中的 tar.gz 压缩包
            _logger.info(f"创建压缩包...")
            tar_buffer = BytesIO()
            current_time = time.time()  # 当前时间戳
            
            with tarfile.open(fileobj=tar_buffer, mode='w:gz') as tar:
                # 添加 JSON 文件
                json_info = tarfile.TarInfo(name=f"{traceid}.json")
                json_bytes = json_content.encode('utf-8')
                json_info.size = len(json_bytes)
                json_info.mtime = current_time  # 设置修改时间
                json_info.mode = 0o644  # 设置文件权限
                tar.addfile(json_info, BytesIO(json_bytes))
                
                # 添加 .p 文件
                p_info = tarfile.TarInfo(name=f"{traceid}.p")
                p_bytes = p_content.encode('utf-8')
                p_info.size = len(p_bytes)
                p_info.mtime = current_time  # 设置修改时间
                p_info.mode = 0o644  # 设置文件权限
                tar.addfile(p_info, BytesIO(p_bytes))
                
                # 添加 .dat 文件
                dat_info = tarfile.TarInfo(name=f"{traceid}.dat")
                dat_bytes = dat_content.encode('utf-8')
                dat_info.size = len(dat_bytes)
                dat_info.mtime = current_time  # 设置修改时间
                dat_info.mode = 0o644  # 设置文件权限
                tar.addfile(dat_info, BytesIO(dat_bytes))
            
            tar_buffer.seek(0)
            
            # 上传压缩包
            remote_tar = os.path.join(work_dir, f"{traceid}.tar.gz")
            _logger.info(f"上传压缩包: {remote_tar}")
            
            sftp = ssh.open_sftp()
            with sftp.open(remote_tar, 'wb') as f:
                f.write(tar_buffer.read())
            sftp.close()
            
            # 解压缩（保留文件时间戳）
            _logger.info(f"远程解压缩...")
            untar_cmd = f"cd {work_dir} && tar -xzf {traceid}.tar.gz --touch && rm {traceid}.tar.gz"
            stdin, stdout, stderr = ssh.exec_command(untar_cmd)
            exit_status = stdout.channel.recv_exit_status()
            
            if exit_status != 0:
                error_msg = stderr.read().decode()
                raise Exception(f"解压缩失败: {error_msg}")
            
            # 设置文件为当前时间（使用 touch 命令）
            _logger.info(f"设置文件时间戳...")
            touch_cmd = f"touch {json_file} {p_file} {dat_file}"
            stdin, stdout, stderr = ssh.exec_command(touch_cmd)
            stdout.channel.recv_exit_status()
            
            _logger.info(f"✅ 文件创建完成（压缩传输）")
            
            ssh.close()
            
            return {
                'json_file': json_file,
                'p_file': p_file,
                'dat_file': dat_file,
                'traceid': traceid,
                'transfer_method': 'compressed'
            }
            
        except Exception as e:
            _logger.error(f"SSH 创建文件失败: {str(e)}")
            raise
    
    def _ensure_remote_dir(self, sftp, path):
        """确保远程目录存在"""
        try:
            sftp.stat(path)
        except IOError:
            # 目录不存在，创建它
            parent = os.path.dirname(path)
            if parent and parent != '/':
                self._ensure_remote_dir(sftp, parent)
            sftp.mkdir(path)
    
    def _generate_p_file_content(self, traceid, work_dir, output_dir, server_config, endpoint):
        """生成 .p 文件内容"""
        additional_path = (endpoint.additional_path or '').strip('/')
        
        # 构建完整路径
        if additional_path:
            output_full = os.path.join(output_dir, traceid + ".run.log")
            work_full = os.path.join(work_dir, traceid + ".dat")
        else:
            output_full = os.path.join(output_dir, traceid + ".run.log")
            work_full = os.path.join(work_dir, traceid + ".dat")
        
        lines = [
            f"output to {output_full}.",  # 添加结尾的点号
            f"input from {work_full}.",   # 添加结尾的点号
            "run xxcommon01.p.",
            "input close.",
            "output close."
        ]
        
        return '\n'.join(lines) + '\n'
    
    def _generate_dat_file_content(self, traceid, json_file, work_dir, output_dir, server_config, endpoint):
        """生成 .dat 文件内容"""
        additional_path = (endpoint.additional_path or '').strip('/')
        
        # 构建输出日志路径
        if additional_path:
            out_log = os.path.join(output_dir, traceid + ".out.log")
        else:
            out_log = os.path.join(output_dir, traceid + ".out.log")
        
        # 第1行：所有参数用双引号包裹，用空格分隔
        line1_parts = [
            f'"{json_file}"',
            f'"{endpoint.application_name}"',
            f'"{out_log}"',
            f'"{server_config.app_username or ""}"',
            f'"{server_config.app_password or ""}"'
        ]
        line1 = ' '.join(line1_parts)  # 用空格分隔
        
        # 第2行：登录选项
        line2 = f'"{server_config.login_options or ""}"'
        
        return line1 + '\n' + line2 + '\n'
    
    @http.route('/api/qad/<string:server_code>/<string:endpoint_name>', 
                type='http', auth='none', methods=['GET', 'POST'], csrf=False)
    def qad_api_call(self, server_code, endpoint_name, **kwargs):
        """
        QAD API 主接口
        
        参数：
        - server_code: 服务器代码
        - endpoint_name: 接口名称
        - api_key: API Key（从 Header 或参数中获取）
        - JSON body: 要处理的数据
        """
        start_time = time.time()
        
        try:
            # 获取 API Key
            api_key = (
                request.httprequest.headers.get('X-API-Key') or
                request.httprequest.headers.get('Authorization', '').replace('Bearer ', '') or
                kwargs.get('api_key')
            )
            
            # 查找接口配置
            endpoint = request.env['qad.api.endpoint'].sudo().search([
                ('server_config_id.server_code', '=', server_code),
                ('endpoint_name', '=', endpoint_name),
                ('active', '=', True),
            ], limit=1)
            
            if not endpoint:
                return self._error_response(
                    404,
                    'NOT_FOUND',
                    f'接口不存在或未启用：{server_code}/{endpoint_name}'
                )
            
            # 验证 API Key
            if endpoint.require_api_key:
                user = self._authenticate_api_key(api_key)
                if not user:
                    return self._error_response(
                        401,
                        'UNAUTHORIZED',
                        'API Key 无效或缺失'
                    )
                
                # 检查用户权限
                if endpoint.allowed_user_ids and user not in endpoint.allowed_user_ids:
                    return self._error_response(
                        403,
                        'FORBIDDEN',
                        '您没有权限访问此接口'
                    )
                
                # 检查请求频率限制
                if not self._check_rate_limit(endpoint, user):
                    return self._error_response(
                        429,
                        'TOO_MANY_REQUESTS',
                        '请求过于频繁，请稍后再试'
                    )
            
            # 获取服务器配置
            server_config = endpoint.server_config_id
            
            if not server_config.active:
                return self._error_response(
                    503,
                    'SERVICE_UNAVAILABLE',
                    '服务器配置未启用'
                )
            
            # 获取 POST 的 JSON 数据
            json_data = None
            if request.httprequest.method == 'POST':
                try:
                    # 从请求体中获取 JSON 数据
                    if request.httprequest.is_json:
                        json_data = request.httprequest.get_json()
                    else:
                        # 尝试解析为 JSON
                        body = request.httprequest.data.decode('utf-8')
                        if body:
                            json_data = json.loads(body)
                except Exception as e:
                    return self._error_response(
                        400,
                        'INVALID_JSON',
                        f'无效的 JSON 数据：{str(e)}'
                    )
            
            if not json_data:
                return self._error_response(
                    400,
                    'NO_DATA',
                    '请使用 POST 方法并提供 JSON 数据'
                )
            
            # 处理 JSON 数据并生成文件
            _logger.info(f"接收到 JSON 数据，准备处理...")
            file_info = self._process_json_data(json_data, server_config, endpoint)
            
            # 计算响应时间
            response_time = time.time() - start_time
            
            # 更新统计信息
            endpoint.sudo().increment_call_stats(
                success=True,
                response_time=response_time
            )
            
            # 返回成功响应
            result_data = {
                'traceid': file_info['traceid'],
                'files_created': {
                    'json_file': file_info['json_file'],
                    'p_file': file_info['p_file'],
                    'dat_file': file_info['dat_file']
                },
                'original_data': json_data  # 包含原始的JSON数据明细
            }
            
            # 如果执行了脚本处理，添加处理结果
            if file_info.get('script_executed'):
                processing_result = file_info.get('processing_result', {})
                return_status = processing_result.get('return_status', 'UNKNOWN')
                
                result_data.update({
                    'script_executed': True,
                    'return_status': return_status,
                    'remote_result_data': processing_result.get('result_data', {})  # 目标服务器的.run.out.json内容
                })
                
                # 根据处理状态设置消息
                if return_status == 'SUCCESS':
                    result_data['message'] = '数据处理成功'
                else:
                    result_data['message'] = f'数据处理失败: {return_status}'
            else:
                result_data.update({
                    'script_executed': False,
                    'return_status': 'ERROR',
                    'message': '文件创建成功，但脚本执行失败'
                })
            
            return self._success_response(result_data, response_time)
            
        except Exception as e:
            _logger.error(f"API 调用失败：{str(e)}")
            
            # 计算响应时间
            response_time = time.time() - start_time
            
            # 更新统计信息
            if 'endpoint' in locals():
                endpoint.sudo().increment_call_stats(
                    success=False,
                    response_time=response_time,
                    error_message=str(e)
                )
            
            return self._error_response(
                500,
                'INTERNAL_ERROR',
                str(e)
            )

    def _success_response(self, data, response_time):
        """返回成功响应"""
        response_data = {
            'success': True,
            'data': data,
            'meta': {
                'response_time': round(response_time, 3),
                'timestamp': datetime.now().isoformat(),
            }
        }
        
        return Response(
            json.dumps(response_data, ensure_ascii=False, indent=2),
            status=200,
            mimetype='application/json'
        )

    def _error_response(self, status_code, error_code, message):
        """返回错误响应"""
        response_data = {
            'success': False,
            'error': {
                'code': error_code,
                'message': message,
            },
            'meta': {
                'timestamp': datetime.now().isoformat(),
            }
        }
        
        return Response(
            json.dumps(response_data, ensure_ascii=False, indent=2),
            status=status_code,
            mimetype='application/json'
        )

    def _execute_processing_script(self, traceid, work_dir, output_dir, server_config, endpoint):
        """
        执行处理脚本
        
        参数：
        - traceid: 追踪ID
        - work_dir: 工作目录
        - output_dir: 输出目录
        - server_config: 服务器配置
        - endpoint: 接口配置
        
        返回：
        - 执行结果字典
        """
        try:
            if server_config.connection_type == 'local':
                return self._execute_script_local(traceid, work_dir, server_config, endpoint)
            elif server_config.connection_type == 'ssh':
                return self._execute_script_ssh(traceid, work_dir, server_config, endpoint)
            else:
                return {'success': False, 'error': '不支持的连接类型'}
                
        except Exception as e:
            _logger.error(f"执行脚本失败: {str(e)}")
            return {'success': False, 'error': str(e)}

    def _execute_script_local(self, traceid, work_dir, server_config, endpoint):
        """本地执行脚本"""
        import subprocess
        
        try:
            # 构建命令
            login_script = server_config.login_script
            p_file_path = os.path.join(work_dir, f"{traceid}.p")
            
            if not os.path.exists(p_file_path):
                return {'success': False, 'error': f'脚本文件不存在: {p_file_path}'}
            
            # 执行命令: login_script p_file_path
            cmd = f"{login_script} {p_file_path}"
            _logger.info(f"执行本地脚本: {cmd}")
            
            result = subprocess.run(
                cmd,
                shell=True,
                capture_output=True,
                text=True,
                timeout=server_config.execution_timeout or 300
            )
            
            if result.returncode == 0:
                _logger.info(f"脚本执行成功")
                return {'success': True, 'output': result.stdout}
            else:
                _logger.error(f"脚本执行失败: {result.stderr}")
                return {'success': False, 'error': result.stderr}
                
        except subprocess.TimeoutExpired:
            _logger.error(f"脚本执行超时")
            return {'success': False, 'error': '脚本执行超时'}
        except Exception as e:
            _logger.error(f"本地脚本执行异常: {str(e)}")
            return {'success': False, 'error': str(e)}

    def _execute_script_ssh_with_connection(self, ssh, traceid, work_dir, output_dir, server_config, endpoint):
        """
        使用已有SSH连接执行脚本 - 优化版本：一次连接完成所有操作
        包括：执行脚本 -> 解析结果 -> 批量移动文件
        
        参数：
        - ssh: 已建立的SSH连接
        - traceid: 追踪ID
        - work_dir: 工作目录
        - output_dir: 输出目录
        - server_config: 服务器配置
        - endpoint: 接口配置
        """
        try:
            # ========== 1. 执行脚本 ==========
            login_script = server_config.login_script
            p_file_path = os.path.join(work_dir, f"{traceid}.p")
            
            cmd = f"{login_script} {p_file_path}"
            _logger.info(f"执行 SSH 脚本: {cmd}")
            
            stdin, stdout, stderr = ssh.exec_command(cmd)
            exit_status = stdout.channel.recv_exit_status()
            
            if exit_status != 0:
                error = stderr.read().decode('utf-8')
                _logger.error(f"SSH 脚本执行失败: {error}")
                return {'success': False, 'error': error}
            
            output = stdout.read().decode('utf-8')
            _logger.info(f"SSH 脚本执行成功")
            
            # ========== 2. 解析结果文件 ==========
            result_file = os.path.join(output_dir, f"{traceid}.run.out.json")
            
            # 读取文件内容
            cat_cmd = f"cat '{result_file}' 2>/dev/null || echo ''"
            stdin, stdout, stderr = ssh.exec_command(cat_cmd)
            file_content = stdout.read().decode('utf-8')
            
            if not file_content:
                return {
                    'success': False,
                    'error': f'结果文件不存在或为空: {result_file}',
                    'return_status': 'ERROR'
                }
            
            # 解析 JSON 内容
            result_data = json.loads(file_content)
            
            # 从 api_status 数组中提取真正的 return_status
            return_status = self._extract_return_status(result_data)
            
            _logger.info(f"SSH解析结果文件成功，return_status: {return_status}")
            
            # ========== 3. 批量移动文件（优化：一次性完成）==========
            # 确定目标目录
            if return_status == 'SUCCESS':
                target_dir = os.path.join(server_config.success_path, endpoint.additional_path or '')
            else:
                target_dir = os.path.join(server_config.error_path, endpoint.additional_path or '')
            
            target_dir = target_dir.rstrip('/')
            
            # 使用一个bash脚本一次性完成所有文件移动操作
            timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
            
            # 使用普通字符串格式化，避免f-string和bash变量冲突
            move_script = """
set -e
mkdir -p '""" + target_dir + """'
for file in '""" + output_dir + """/""" + traceid + """'*; do
    if [ -f "$file" ]; then
        filename=$(basename "$file")
        target='""" + target_dir + """'/$filename
        if [ -f "$target" ]; then
            name="${filename%.*}"
            ext="${filename##*.}"
            if [ "$name" = "$filename" ]; then
                target='""" + target_dir + """'/${filename}_""" + timestamp + """
            else
                target='""" + target_dir + """'/${name}_""" + timestamp + """.${ext}
            fi
        fi
        mv "$file" "$target"
        echo "MOVED:$file:$target"
    fi
done
"""
            
            stdin, stdout, stderr = ssh.exec_command(move_script)
            move_exit_status = stdout.channel.recv_exit_status()
            
            if move_exit_status == 0:
                move_output = stdout.read().decode('utf-8')
                moved_files = []
                for line in move_output.strip().split('\n'):
                    if line.startswith('MOVED:'):
                        parts = line.split(':')
                        if len(parts) >= 3:
                            source = parts[1]
                            target = parts[2]
                            moved_files.append(target)
                            _logger.info(f"SSH移动文件: {source} -> {target}")
                
                _logger.info(f"SSH文件移动完成，共移动 {len(moved_files)} 个文件到 {target_dir}")
            else:
                error = stderr.read().decode('utf-8')
                _logger.error(f"SSH批量移动文件失败: {error}")
                moved_files = []
            
            # 返回完整的结果
            return {
                'success': True,
                'output': output,
                'return_status': return_status,
                'result_data': result_data,
                'result_file': result_file,
                'files_moved': moved_files
            }
                
        except Exception as e:
            _logger.error(f"SSH 脚本执行异常: {str(e)}")
            return {'success': False, 'error': str(e)}
    
    def _execute_script_ssh(self, traceid, work_dir, server_config, endpoint):
        """
        SSH 执行脚本 - 优化版本：一次连接完成所有操作
        包括：执行脚本 -> 解析结果 -> 移动文件
        """
        import paramiko
        
        ssh = None
        try:
            # 创建 SSH 客户端
            ssh = paramiko.SSHClient()
            ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            
            # 连接参数
            connect_params = {
                'hostname': server_config.host,
                'port': server_config.port,
                'username': server_config.ssh_username,
                'timeout': server_config.connection_timeout,
            }
            
            # 根据认证方式设置参数
            if server_config.auth_type == 'password':
                connect_params['password'] = server_config.ssh_password
            elif server_config.auth_type == 'key':
                if server_config.ssh_private_key:
                    from io import StringIO
                    key_file = StringIO(server_config.ssh_private_key)
                    pkey = paramiko.RSAKey.from_private_key(
                        key_file,
                        password=server_config.ssh_key_passphrase
                    )
                    connect_params['pkey'] = pkey
            
            _logger.info(f"连接 SSH（一次连接完成所有操作）：{server_config.host}:{server_config.port}")
            ssh.connect(**connect_params)
            
            # ========== 1. 执行脚本 ==========
            login_script = server_config.login_script
            p_file_path = os.path.join(work_dir, f"{traceid}.p")
            
            cmd = f"{login_script} {p_file_path}"
            _logger.info(f"执行 SSH 脚本: {cmd}")
            
            stdin, stdout, stderr = ssh.exec_command(cmd)
            exit_status = stdout.channel.recv_exit_status()
            
            if exit_status != 0:
                error = stderr.read().decode('utf-8')
                _logger.error(f"SSH 脚本执行失败: {error}")
                ssh.close()
                return {'success': False, 'error': error}
            
            output = stdout.read().decode('utf-8')
            _logger.info(f"SSH 脚本执行成功")
            
            # ========== 2. 解析结果文件 ==========
            output_dir = server_config.output_path
            if endpoint.additional_path:
                output_dir = os.path.join(output_dir, endpoint.additional_path.strip('/'))
            
            result_file = os.path.join(output_dir, f"{traceid}.run.out.json")
            
            # 检查文件是否存在
            check_cmd = f"test -f '{result_file}' && echo 'EXISTS' || echo 'NOT_EXISTS'"
            stdin, stdout, stderr = ssh.exec_command(check_cmd)
            file_exists = stdout.read().decode('utf-8').strip()
            
            if file_exists != 'EXISTS':
                ssh.close()
                return {
                    'success': False,
                    'error': f'结果文件不存在: {result_file}',
                    'return_status': 'ERROR'
                }
            
            # 读取文件内容
            cat_cmd = f"cat '{result_file}'"
            stdin, stdout, stderr = ssh.exec_command(cat_cmd)
            file_content = stdout.read().decode('utf-8')
            
            if not file_content:
                ssh.close()
                return {
                    'success': False,
                    'error': f'结果文件为空: {result_file}',
                    'return_status': 'ERROR'
                }
            
            # 解析 JSON 内容
            result_data = json.loads(file_content)
            
            # 从 api_status 数组中提取真正的 return_status
            return_status = self._extract_return_status(result_data)
            
            _logger.info(f"SSH解析结果文件成功，return_status: {return_status}")
            
            # ========== 3. 移动文件 ==========
            # 确定目标目录
            if return_status == 'SUCCESS':
                target_dir = os.path.join(server_config.success_path, endpoint.additional_path or '')
            else:
                target_dir = os.path.join(server_config.error_path, endpoint.additional_path or '')
            
            target_dir = target_dir.rstrip('/')
            
            # 确保目标目录存在
            mkdir_cmd = f"mkdir -p '{target_dir}'"
            stdin, stdout, stderr = ssh.exec_command(mkdir_cmd)
            stdout.channel.recv_exit_status()
            
            # 查找要移动的文件
            find_cmd = f"find '{output_dir}' -name '{traceid}*' -type f"
            stdin, stdout, stderr = ssh.exec_command(find_cmd)
            files_to_move = stdout.read().decode('utf-8').strip().split('\n')
            files_to_move = [f for f in files_to_move if f]  # 移除空字符串
            
            moved_files = []
            for file_path in files_to_move:
                if file_path:
                    filename = os.path.basename(file_path)
                    target_path = os.path.join(target_dir, filename)
                    
                    # 如果目标文件已存在，添加时间戳
                    timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
                    test_cmd = f"test -f '{target_path}' && echo 'EXISTS' || echo 'NOT_EXISTS'"
                    stdin, stdout, stderr = ssh.exec_command(test_cmd)
                    exists = stdout.read().decode('utf-8').strip()
                    
                    if exists == 'EXISTS':
                        name, ext = os.path.splitext(filename)
                        filename = f"{name}_{timestamp}{ext}"
                        target_path = os.path.join(target_dir, filename)
                    
                    # 移动文件
                    move_cmd = f"mv '{file_path}' '{target_path}'"
                    stdin, stdout, stderr = ssh.exec_command(move_cmd)
                    move_exit_status = stdout.channel.recv_exit_status()
                    
                    if move_exit_status == 0:
                        moved_files.append(target_path)
                        _logger.info(f"SSH移动文件: {file_path} -> {target_path}")
                    else:
                        error = stderr.read().decode('utf-8')
                        _logger.error(f"SSH移动文件失败: {file_path} -> {target_path}, 错误: {error}")
            
            _logger.info(f"SSH文件移动完成，共移动 {len(moved_files)} 个文件到 {target_dir}")
            
            # 关闭连接
            ssh.close()
            
            # 返回完整的结果
            return {
                'success': True,
                'output': output,
                'return_status': return_status,
                'result_data': result_data,
                'result_file': result_file,
                'files_moved': moved_files
            }
                
        except Exception as e:
            _logger.error(f"SSH 脚本执行异常: {str(e)}")
            if ssh:
                ssh.close()
            return {'success': False, 'error': str(e)}

    def _extract_return_status(self, result_data):
        """
        从结果数据中提取真正的 return_status
        优先从 api_status 数组中提取
        
        参数：
        - result_data: 结果数据字典
        
        返回：
        - return_status 字符串
        """
        try:
            # 尝试从多个可能的路径提取 return_status
            # 1. 从 dsBackflushDetail.api_status 数组中提取（最优先）
            if isinstance(result_data, dict):
                ds_detail = result_data.get('dsBackflushDetail', {})
                if isinstance(ds_detail, dict):
                    api_status_list = ds_detail.get('api_status', [])
                    if isinstance(api_status_list, list) and len(api_status_list) > 0:
                        first_status = api_status_list[0]
                        if isinstance(first_status, dict):
                            status = first_status.get('return_status')
                            if status:
                                return status
                
                # 2. 从根级别的 return_status 提取（备用）
                status = result_data.get('return_status')
                if status:
                    return status
            
            # 3. 默认返回 UNKNOWN
            return 'UNKNOWN'
            
        except Exception as e:
            _logger.error(f"提取 return_status 失败: {str(e)}")
            return 'UNKNOWN'

    def _parse_result_file(self, traceid, output_dir, server_config, endpoint):
        """
        解析结果文件（在目标服务器上）
        
        参数：
        - traceid: 追踪ID
        - output_dir: 输出目录
        - server_config: 服务器配置
        - endpoint: 接口配置
        
        返回：
        - 解析结果字典
        """
        try:
            if server_config.connection_type == 'local':
                return self._parse_result_file_local(traceid, output_dir, server_config, endpoint)
            elif server_config.connection_type == 'ssh':
                return self._parse_result_file_ssh(traceid, output_dir, server_config, endpoint)
            else:
                return {
                    'success': False,
                    'error': '不支持的连接类型',
                    'return_status': 'ERROR'
                }
                
        except Exception as e:
            _logger.error(f"解析结果文件失败: {str(e)}")
            return {
                'success': False,
                'error': str(e),
                'return_status': 'ERROR'
            }

    def _parse_result_file_local(self, traceid, output_dir, server_config, endpoint):
        """本地解析结果文件"""
        try:
            # 构建结果文件路径
            result_file = os.path.join(output_dir, f"{traceid}.run.out.json")
            
            if not os.path.exists(result_file):
                return {
                    'success': False,
                    'error': f'结果文件不存在: {result_file}',
                    'return_status': 'ERROR'
                }
            
            # 读取并解析 JSON 文件
            with open(result_file, 'r', encoding='utf-8') as f:
                result_data = json.load(f)
            
            # 从 api_status 数组中提取真正的 return_status
            return_status = self._extract_return_status(result_data)
            
            _logger.info(f"本地解析结果文件成功，return_status: {return_status}")
            
            return {
                'success': True,
                'return_status': return_status,
                'result_data': result_data,
                'result_file': result_file
            }
            
        except Exception as e:
            _logger.error(f"本地解析结果文件失败: {str(e)}")
            return {
                'success': False,
                'error': str(e),
                'return_status': 'ERROR'
            }

    def _parse_result_file_ssh(self, traceid, output_dir, server_config, endpoint):
        """SSH解析结果文件"""
        import paramiko
        
        try:
            # 创建 SSH 客户端
            ssh = paramiko.SSHClient()
            ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            
            # 连接参数
            connect_params = {
                'hostname': server_config.host,
                'port': server_config.port,
                'username': server_config.ssh_username,
                'timeout': server_config.connection_timeout,
            }
            
            # 根据认证方式设置参数
            if server_config.auth_type == 'password':
                connect_params['password'] = server_config.ssh_password
            elif server_config.auth_type == 'key':
                if server_config.ssh_private_key:
                    from io import StringIO
                    key_file = StringIO(server_config.ssh_private_key)
                    pkey = paramiko.RSAKey.from_private_key(
                        key_file,
                        password=server_config.ssh_key_passphrase
                    )
                    connect_params['pkey'] = pkey
            
            _logger.info(f"连接 SSH 解析结果文件：{server_config.host}:{server_config.port}")
            ssh.connect(**connect_params)
            
            # 构建结果文件路径
            result_file = os.path.join(output_dir, f"{traceid}.run.out.json")
            
            # 检查文件是否存在
            check_cmd = f"test -f '{result_file}' && echo 'EXISTS' || echo 'NOT_EXISTS'"
            stdin, stdout, stderr = ssh.exec_command(check_cmd)
            file_exists = stdout.read().decode('utf-8').strip()
            
            if file_exists != 'EXISTS':
                ssh.close()
                return {
                    'success': False,
                    'error': f'结果文件不存在: {result_file}',
                    'return_status': 'ERROR'
                }
            
            # 读取文件内容
            cat_cmd = f"cat '{result_file}'"
            stdin, stdout, stderr = ssh.exec_command(cat_cmd)
            file_content = stdout.read().decode('utf-8')
            
            if not file_content:
                ssh.close()
                return {
                    'success': False,
                    'error': f'结果文件为空: {result_file}',
                    'return_status': 'ERROR'
                }
            
            # 解析 JSON 内容
            result_data = json.loads(file_content)
            
            # 提取 return_status
            return_status = result_data.get('return_status', 'UNKNOWN')
            
            _logger.info(f"SSH解析结果文件成功，return_status: {return_status}")
            
            ssh.close()
            
            return {
                'success': True,
                'return_status': return_status,
                'result_data': result_data,
                'result_file': result_file
            }
            
        except Exception as e:
            _logger.error(f"SSH解析结果文件失败: {str(e)}")
            if 'ssh' in locals():
                ssh.close()
            return {
                'success': False,
                'error': str(e),
                'return_status': 'ERROR'
            }

    def _move_result_files(self, traceid, output_dir, server_config, endpoint, result_data):
        """
        根据处理结果移动文件（在目标服务器上）
        
        参数：
        - traceid: 追踪ID
        - output_dir: 输出目录
        - server_config: 服务器配置
        - endpoint: 接口配置
        - result_data: 处理结果数据
        """
        try:
            if server_config.connection_type == 'local':
                return self._move_result_files_local(traceid, output_dir, server_config, endpoint, result_data)
            elif server_config.connection_type == 'ssh':
                return self._move_result_files_ssh(traceid, output_dir, server_config, endpoint, result_data)
            else:
                _logger.warning(f"不支持的连接类型，跳过文件移动")
                
        except Exception as e:
            _logger.error(f"移动文件失败: {str(e)}")
            # 文件移动失败不应该影响整个流程，只记录错误

    def _move_result_files_local(self, traceid, output_dir, server_config, endpoint, result_data):
        """本地移动文件"""
        try:
            return_status = result_data.get('return_status', 'ERROR')
            
            # 确定目标目录
            if return_status == 'SUCCESS':
                target_dir = os.path.join(server_config.success_path, endpoint.additional_path or '')
            else:
                target_dir = os.path.join(server_config.error_path, endpoint.additional_path or '')
            
            # 确保目标目录存在
            os.makedirs(target_dir, exist_ok=True)
            
            # 移动以 traceid 开头的所有文件
            import glob
            pattern = os.path.join(output_dir, f"{traceid}*")
            files_to_move = glob.glob(pattern)
            
            moved_files = []
            for file_path in files_to_move:
                if os.path.isfile(file_path):
                    filename = os.path.basename(file_path)
                    target_path = os.path.join(target_dir, filename)
                    
                    # 如果目标文件已存在，添加时间戳
                    if os.path.exists(target_path):
                        name, ext = os.path.splitext(filename)
                        timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
                        filename = f"{name}_{timestamp}{ext}"
                        target_path = os.path.join(target_dir, filename)
                    
                    os.rename(file_path, target_path)
                    moved_files.append(target_path)
                    _logger.info(f"本地移动文件: {file_path} -> {target_path}")
            
            _logger.info(f"本地文件移动完成，共移动 {len(moved_files)} 个文件到 {target_dir}")
            
        except Exception as e:
            _logger.error(f"本地移动文件失败: {str(e)}")

    def _move_result_files_ssh(self, traceid, output_dir, server_config, endpoint, result_data):
        """SSH移动文件"""
        import paramiko
        
        try:
            # 创建 SSH 客户端
            ssh = paramiko.SSHClient()
            ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            
            # 连接参数
            connect_params = {
                'hostname': server_config.host,
                'port': server_config.port,
                'username': server_config.ssh_username,
                'timeout': server_config.connection_timeout,
            }
            
            # 根据认证方式设置参数
            if server_config.auth_type == 'password':
                connect_params['password'] = server_config.ssh_password
            elif server_config.auth_type == 'key':
                if server_config.ssh_private_key:
                    from io import StringIO
                    key_file = StringIO(server_config.ssh_private_key)
                    pkey = paramiko.RSAKey.from_private_key(
                        key_file,
                        password=server_config.ssh_key_passphrase
                    )
                    connect_params['pkey'] = pkey
            
            _logger.info(f"连接 SSH 移动文件：{server_config.host}:{server_config.port}")
            ssh.connect(**connect_params)
            
            return_status = result_data.get('return_status', 'ERROR')
            
            # 确定目标目录
            if return_status == 'SUCCESS':
                target_dir = os.path.join(server_config.success_path, endpoint.additional_path or '')
            else:
                target_dir = os.path.join(server_config.error_path, endpoint.additional_path or '')
            
            # 确保目标目录存在
            mkdir_cmd = f"mkdir -p '{target_dir}'"
            stdin, stdout, stderr = ssh.exec_command(mkdir_cmd)
            stdout.channel.recv_exit_status()
            
            # 查找要移动的文件
            find_cmd = f"find '{output_dir}' -name '{traceid}*' -type f"
            stdin, stdout, stderr = ssh.exec_command(find_cmd)
            files_to_move = stdout.read().decode('utf-8').strip().split('\n')
            files_to_move = [f for f in files_to_move if f]  # 移除空字符串
            
            moved_files = []
            for file_path in files_to_move:
                if file_path:
                    filename = os.path.basename(file_path)
                    target_path = os.path.join(target_dir, filename)
                    
                    # 如果目标文件已存在，添加时间戳
                    timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
                    test_cmd = f"test -f '{target_path}' && echo 'EXISTS' || echo 'NOT_EXISTS'"
                    stdin, stdout, stderr = ssh.exec_command(test_cmd)
                    exists = stdout.read().decode('utf-8').strip()
                    
                    if exists == 'EXISTS':
                        name, ext = os.path.splitext(filename)
                        filename = f"{name}_{timestamp}{ext}"
                        target_path = os.path.join(target_dir, filename)
                    
                    # 移动文件
                    move_cmd = f"mv '{file_path}' '{target_path}'"
                    stdin, stdout, stderr = ssh.exec_command(move_cmd)
                    exit_status = stdout.channel.recv_exit_status()
                    
                    if exit_status == 0:
                        moved_files.append(target_path)
                        _logger.info(f"SSH移动文件: {file_path} -> {target_path}")
                    else:
                        error = stderr.read().decode('utf-8')
                        _logger.error(f"SSH移动文件失败: {file_path} -> {target_path}, 错误: {error}")
            
            ssh.close()
            _logger.info(f"SSH文件移动完成，共移动 {len(moved_files)} 个文件到 {target_dir}")
            
        except Exception as e:
            _logger.error(f"SSH移动文件失败: {str(e)}")
            if 'ssh' in locals():
                ssh.close()

